/**
*******************************************************************************************************************
*@file  main.c
*@brief 主函数
*@author    花满楼
*@date      2020-07-01
*@version  V1
*@attention
            1、电池容量7.5Ah
            2、最大放电功率10500W
			3、三元电芯
			4、硬件看门狗复位窗口时间728.6ms-1214.4ms
*******************************************************************************************************************
*/
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "adc.h"
#include "rs485.h"
#include "timer.h"
#include "bq79616.h"
#include "bq79600.h"
#include "spi.h"
#include "eeprom.h"
#include "ads1260.h"
#include "iwdg.h"
#include "protect.h"
#include "sd2405.h"
#include "can.h"
#include "relay_ctl.h"
#include "fan.h"
#include "debug.h"
#include "temper.h"
#include "balance.h"

#include "SOC_AH.h"
#include "SOC_AH_private.h"
#include "SOH_cycle.h"
#include "SOH_cycle_private.h"
#include "bms_balance.h"
#include "bms_balance_private.h"



#define DEBUG_EEP 0        ///<0：不调试EEP；1：调试
#define DEBUG_IWEG 0       ///<0：不调试看门狗；1：调试
#define DEBUG_RLY_FAIL 0   ///<继电器失效检测：1：调试
/**
*@brief 主函数
*@param[in]   none
*@attention
    *电流采集时间10ms，while()函数中的循环暂时按照10ms一个周波，同时需要关注主函数执行的时间
 */

//u8 mid_buffer[5][40];
int main(void)
{
	u32 pre_time = 0;       	//前一次的定时时间
	u8 pack_tol_status;     	//系统综合状态
	s16 load_vol;               //负载电压
	u16 cell_max_temp;          //电芯最大温度
	u16 pack_protect, pack_alarm;   //设备保护和设备告警综合状态，用于故障灯的控制
	u8 rs485_fail = 0;              //485失效
	u16 temp_soc,temp_soh;		//为验证SOC和SOH的验证功能
	u8 powerdown_cmd=0;		//强制下电指令
	u16 cell_temp[10];		//电芯的温度数值，偏移-40C
	u8 i,cell_bal_fail=0,mud_bal_fail=0;	//电芯均衡失效告警、模组均衡失效告警
	u8 rtc_read_count; //用于对RTC读取时间计数，400ms读取一次RTC
	u16 bq_balance[4];
	

	HAL_Init();                   //初始化HAL库
	Stm32_Clock_Init(336, 8, 2, 7);    //设置时钟,168Mhz
	delay_init(168);
	//	Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
	//    delay_init(180);                //初始化延时函数
	/*********片上外设初始化*********/
	Commin_IO_Init();               /*初始化被用作通用IO的端口*/
	Fan_Init();                     /*对风扇接口初始化*/
	Relay_Init();                   /*继电器控制引脚和反馈引脚初始化*/
	Get_Address();        			/*读取设备地址*/
	RS232_Init(UART_Bound);         /*初始化UART7为RS232*/
	RS485_Init(UART_Bound);         /*初始化USART3为RS485*/
	TIM3_Init(100 - 1, 8400 - 1);   /*定时器3初始化，定时器时钟为84M，分频系数为8400-1，10ms*/
	CAN1_Mode_Init(CAN_SJW_1TQ, CAN_BS2_6TQ, CAN_BS1_7TQ, 12, CAN_MODE_NORMAL);    /*CAN1初始化,波特率250Kbps*/
	CAN2_Mode_Init(CAN_SJW_1TQ, CAN_BS2_6TQ, CAN_BS1_7TQ, 12, CAN_MODE_NORMAL);    /*CAN2初始化,波特率250Kbps*/

	//	CAN1_Mode_Init(CAN_SJW_1TQ,CAN_BS2_6TQ,CAN_BS1_8TQ,6,CAN_MODE_NORMAL); //CAN初始化,波特率500Kbps 
	//	CAN2_Mode_Init(CAN_SJW_1TQ,CAN_BS2_6TQ,CAN_BS1_8TQ,6,CAN_MODE_NORMAL); //CAN初始化,波特率500Kbps 
	ADC3_Init();                    /*初始化ADC3*/
	SPI_Init();                     /*SPI初始化*/
	Fan_Init();
	BQ796xx_Init();

	delay_ms(50);
	/****************************EEP调试**************************/	
	EEP_Write();
	/****************************RTC调试**************************/
	RTC_Init();
	//	SD2405_init();
	SD2405_Start();	//开启实时时钟	
	/****************************EEP上电测试**************************/
	EEP_POR_Read(); //上电EEP信号读取
	/****************************电流和高压采集调试**************************/
	Init_Ads1260();
	/************************程序开始******************************/
	Fan_Init();
	/*************************SOC初始化****************************/
	SOC_AH_initialize();
	bms_balance_initialize();
	SocHistory = 10;
	SohHistory = 10;
    while (1)
    {		
        if (pre_time != timer_count) //基本确保10ms进入一次
        {
			Bq79616_Main_Mears();
			Cell_Vol_filter();
			Bq79616_AUX_Mears();		
			Get_Temper(cell_temp);
			Temp_Vol_filter(cell_temp);
			/*****************电流和高压采集****************/
			Sampl_VolORCur();
			/*****************读取错误故障位*****************/
			if(1!=BQ79600_FLAUT)
			{
				Get_Fault();	//需要确认故障低压还是故障高压
			}
			/*****************SOC测试******************/
			BatCurrent = 0;
			CellVltgAvg = 2800;
			TempAvg = 25;
			SOC_AH_step();
			AccChaAH_EE = 5250;
			AccDchaAH_EE = 6750;
			SOH_cycle_step();
			
			for(i=0;i<64;i++)
			{
				rtb_VltgRecv[i] = 3800;
			}
			rtb_VltgRecv[52] = 4100;
			rtb_VltgRecv[53] = 4100;
			rtb_VltgRecv[27] = 4100;
			MinCellVolt = 3800;
			BalModeCondition= 1;
			bms_balance_step();
			
			for(i=0;i<15;i++)
			{
				if(bms_balance_B.BMS_BalanceEn[i]>0)
				{
					bq_balance[0] |= 1<<i;
					bms_balance_B.BMS_BalanceEn[i+1] = 0;
				}
				else
					bq_balance[0] &= ~(1<<i);
				if(bms_balance_B.BMS_BalanceEn[i+16]>0)
				{
					bq_balance[1] |= 1<<i;
					bms_balance_B.BMS_BalanceEn[i+17] = 0;
				}
				else
					bq_balance[1] &= ~(1<<i);
				if(bms_balance_B.BMS_BalanceEn[i+32]>0)
				{
					bq_balance[2] |= 1<<i;
					bms_balance_B.BMS_BalanceEn[i+33] = 0;
				}
				else
					bq_balance[2] &= ~(1<<i);
				if(bms_balance_B.BMS_BalanceEn[i+48]>0)
				{
					bq_balance[3] |= 1<<i;
					bms_balance_B.BMS_BalanceEn[i+49] = 0;
				}
				else
					bq_balance[3] &= ~(1<<i);
			}
			/*****************pack保护*****************/
            cell_max_temp = Singel_Protect(&Pack_Mes_Tol.Pack_Cur, load_vol,cell_temp);
            /*****************继电器控制*****************/
			powerdown_cmd = Debug_BMS_Power(Control_Reg.Control3.Word);//判断下电命令
			Power_Out_CTL(load_vol, Pack_Mes_Tol.Pack_Vol);	
			/*****************SOC和SOH的矫正模式*****************/
			if(0 != Control_Reg.Control2.Word)	//进入SOC和SOH的矫正模式
				Debgu_SOC_SOH(temp_soc,temp_soh);
            /*****************CAN通讯*****************/
			CAN1_SendToPack(Pack_Addr);
//			CAN2_Send_Msg(8);//CAN2发送测试
            /****************运行故障和SOC的LED显示******************/
			if(0 == Control_Reg.Control1.Word)	//否则上面程序会进入调试过程
			{
				RUN_ALR_LED(&pack_protect, &pack_alarm, &rs485_fail, pack_tol_status);
				SOC_Display(Pack_Mes_Tol.Pack_SOC, pack_tol_status);			
			}
            pack_protect = Alarm_Reg.Serious_Alarm1.Word | Alarm_Reg.Serious_Alarm2.Word;
            pack_alarm = Alarm_Reg.Slight_Alarm1.Word | Alarm_Reg.Slight_Alarm2.Word;
            /****************485通讯******************/
//            Get_Address();        /*读取设备地址*/
			Refresh();
            Collect();
            rs485_fail = RS485_Data();
            /****************风扇控制******************/
			if(0 == Control_Reg.Control1.Word)	//否则上面程序会进入调试过程
				Fan_CTL(cell_max_temp); //风扇控制函数
//			
//			Bq79616_ShutDown();
//			Bq79616_Sleep();

//	cell_bal_fail = Bq79616_Balance(BQ79616_ADR_S1, 0x05, 0x01, 0x00); //电芯均衡函数
	/****************模组均衡******************/
//	mud_bal_fail = Bq79616_Moudle_Balance(0x01, 0x01, 0x01);//单模组均衡（单BQ79616）

#if DEBUG_IWEG
            IWDG_Feed();    //喂狗
#endif
#if DEBUG_EEP
            EEP_Write();    //EEP故障数据以及SOC等写入
#endif
			/*****************RTC*****************/		
			rtc_read_count++;
			if(rtc_read_count>=40)//400ms
			{
				rtc_read_count = 0;
				Get_SD2405Time();
			}
			pre_time = timer_count;
//			delay_ms(10);
        }
    }
}
